package lab.dexter.bbsreader;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import lab.dexter.bbsreader.utils.AccountEditor;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;



public class NewSMTHDroid extends ListActivity {
	
	
	private final int ACTIVITY_ADD = 0;
	private final int ACTIVITY_EDIT = 1;
	
	private final int DIALOG_NETWORK_ERROR = 1;
	
	private List<DataSetObserver> mObserverList;
	private AccountListAdapter mAdapter; 
	
	private class AccountListAdapter implements ListAdapter { 
		// i'm sure there must be a better base class to extend from
		private SharedPreferences mPrefs; 
		
		private static final String PREF_NUM_ACCOUNT = "NUM_ACCOUNT";
		private static final String PREF_USERNAME_PREFIX = "ACC_USR_";
		private static final String PREF_PASSWORD_PREFIX = "ACC_PWD_";

		
		private class Account {
			public String user;
			public String pwd;
			public boolean loading; 
			
			public Account(String user_, String pwd_) {
				user = user_;
				pwd = pwd_;
				loading = false;
			}
		}
		
		private List<Account> accounts;
		
		public AccountListAdapter(SharedPreferences prefs) {
			accounts = new ArrayList<Account>();
			mObserverList = new ArrayList<DataSetObserver>();
			mPrefs = prefs;
			
			int numAccount = prefs.getInt(PREF_NUM_ACCOUNT, 0);
			if (numAccount == 0) {
				prefs.edit().putString(PREF_USERNAME_PREFIX + 0, "guest").putString(PREF_PASSWORD_PREFIX + 0, "").putInt(PREF_NUM_ACCOUNT, 1).commit();
				numAccount = prefs.getInt(PREF_NUM_ACCOUNT, 0);
				assert(numAccount == 1);
			}
			
			for(int i = 0; i < numAccount; i++) {
				String user = prefs.getString(PREF_USERNAME_PREFIX + i, null);
				String pwd = prefs.getString(PREF_PASSWORD_PREFIX + i, null);
				assert(user != null && pwd != null);
				accounts.add(new Account(user, pwd));
			}
		}

		public boolean areAllItemsEnabled() {
			return true;
		}

		public boolean isEnabled(int arg0) {
			return true;
		}

		public int getCount() {
			return accounts.size() + 1; // add account button
		}

		public Object getItem(int position) {
			if(position == accounts.size()) {
				// add account
				return null;
			}
			return accounts.get(position);
		}

		public long getItemId(int position) {
			return position;
		}

		public int getItemViewType(int position) {
			if(position == accounts.size()) {
				return 1;
			}
			return 0;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			View view = convertView;
			if(position >= accounts.size()) {
				// add account button
				if(view == null) {
					LayoutInflater vi = (LayoutInflater)(NewSMTHDroid.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE));
					view = vi.inflate(android.R.layout.simple_list_item_1, null);
				}
				TextView tv = (TextView)view.findViewById(android.R.id.text1);
				tv.setText("(Add new account...)");
			}
			else {
				if(view == null) {
					LayoutInflater vi = (LayoutInflater)(NewSMTHDroid.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE));
					view = vi.inflate(R.layout.account_item, null);
				}
				TextView tv = (TextView)view.findViewById(R.id.account);
				tv.setText(accounts.get(position).user);
				tv = (TextView)view.findViewById(R.id.status);
				if(accounts.get(position).loading) {
					tv.setText("Signing in...");
				}
				else if(NewSMTHHttpClient.getClient().isLoggedIn(accounts.get(position).user)) {
					tv.setText("Logged in");
				}
				else {
					tv.setText("");
				}
			}
			return view;
		}

		public int getViewTypeCount() {
			return 2;
		}

		public boolean hasStableIds() {
			return false;
		}

		public boolean isEmpty() {
			return false;
		}

		public void registerDataSetObserver(DataSetObserver observer) {
			mObserverList.add(observer);			
		}

		public void unregisterDataSetObserver(DataSetObserver observer) {
			for (Iterator<DataSetObserver> it = mObserverList.iterator(); it.hasNext();) {
				DataSetObserver ob = it.next();
				if (ob.equals(observer)) {
					it.remove();
				}
			}
		}
		
		public void notifyDataChanged() {
			for (Iterator<DataSetObserver> it = mObserverList.iterator(); it.hasNext();) {
				DataSetObserver ob = it.next();
				ob.onChanged();
			}
		}
		
		public void onClick(int position) {
			if(position >= accounts.size()) {
				onLongClick(position);
			}
			else {
				// login (after logout, if necessary), and jump to portal
				NewSMTHHttpClient client = NewSMTHHttpClient.getClient();
				//NewSMTHDroid.this.setProgressBarIndeterminate(true);
				Account account = accounts.get(position);
				try {
					account.loading = true;
					this.notifyDataChanged();
					client.login(account.user, account.pwd);
					account.loading = false;
					this.notifyDataChanged();
				} catch (IOException e) {
					NewSMTHDroid.this.showDialog(DIALOG_NETWORK_ERROR);
					return;
				}
				//NewSMTHDroid.this.setProgressBarIndeterminate(false);
				Intent intent = new Intent(NewSMTHDroid.this, Portal.class);
				intent.setAction(Intent.ACTION_VIEW);
				startActivity(intent);
			}
		}
		
		public boolean onLongClick(int position) {
			Intent intent = new Intent(NewSMTHDroid.this, AccountEditor.class);
			if(position >= accounts.size() || position == 0) {
				intent.setAction(Intent.ACTION_INSERT);
				startActivityForResult(intent, ACTIVITY_ADD);
			}
			else {
				intent.setAction(Intent.ACTION_EDIT);			
				Account account = accounts.get(position);
				intent.putExtra(AccountEditor.PARAM_USERNAME, account.user);
				intent.putExtra(AccountEditor.PARAM_PASSWORD, account.pwd);
				startActivityForResult(intent, ACTIVITY_EDIT);
			}
			return true;
		}
		
		public void addAccount(String usr, String pwd) {
			mPrefs.edit().putString(PREF_USERNAME_PREFIX + accounts.size(), usr)
				.putString(PREF_PASSWORD_PREFIX + accounts.size(), pwd)
				.putInt(PREF_NUM_ACCOUNT, accounts.size() + 1)
				.commit();
			accounts.add(new Account(usr, pwd));
		}
		
		public boolean updateAccount(String usr, String pwd) {
			for (int i = 0; i < accounts.size(); i++) {
				Account account = accounts.get(i);
				if(account.user.equals(usr)) {
					account.pwd = pwd;
					mPrefs.edit().putString(PREF_PASSWORD_PREFIX + i, pwd).commit();
					return true;
				}
			}
			return false;
		}
		
		public void deleteAccount(String usr) {
			int idx = 0;
			boolean flag = false;
			for (int i = 0; i < accounts.size(); i++) {
				Account account = accounts.get(i);
				if(flag) {
					mPrefs.edit().putString(PREF_USERNAME_PREFIX + (i-1), account.user)
						.putString(PREF_PASSWORD_PREFIX + (i-1), account.pwd)
						.commit();
				}
				else if(account.user.equals(usr)) {
					idx = i;
					flag = true;
				}
			}
			if(flag) {
				mPrefs.edit().putInt(PREF_NUM_ACCOUNT, accounts.size() - 1)
					.remove(PREF_USERNAME_PREFIX + (accounts.size() - 1))
					.remove(PREF_PASSWORD_PREFIX + (accounts.size() - 1))
					.commit();
				accounts.remove(idx);
			}
		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(resultCode == Activity.RESULT_OK) {
			if(data.getAction().equals(Intent.ACTION_EDIT)) {
				String usr = data.getStringExtra(AccountEditor.PARAM_USERNAME);
				
				if(usr.length() == 0) return;
				
				String pwd = data.getStringExtra(AccountEditor.PARAM_PASSWORD);
				if(requestCode == ACTIVITY_ADD) {
					if(mAdapter.updateAccount(usr, pwd) == false) {
						mAdapter.addAccount(usr, pwd);
					}
				}
				else {
					// requestCode == ACTIVITY_EDIT
					mAdapter.updateAccount(usr, pwd);
				}
			}
			else if(data.getAction().equals(Intent.ACTION_DELETE) 
					&& requestCode == ACTIVITY_EDIT) {
				String usr = data.getStringExtra(AccountEditor.PARAM_USERNAME);
				mAdapter.deleteAccount(usr);
			}
			this.getListView().invalidate();
			mAdapter.notifyDataChanged();
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		SharedPreferences prefs = this.getPreferences(Context.MODE_PRIVATE);

		final AccountListAdapter adapter = new AccountListAdapter(prefs);
		mAdapter = adapter;
		this.setListAdapter(adapter);
		
		ListView lv = this.getListView();
		lv.setOnItemClickListener(new OnItemClickListener() {

			public void onItemClick(AdapterView<?> parent, View view, int position,
					long id) {
				adapter.onClick(position);
			}
			
		});
		lv.setOnItemLongClickListener(new OnItemLongClickListener() {

			public boolean onItemLongClick(AdapterView<?> parent, View view,
					int position, long id) {
				return adapter.onLongClick(position);
			}
			
		});
		
//		
//		Intent intent = new Intent(NewSMTHDroid.this, ListBrowser.class);
//		intent.setAction(Intent.ACTION_VIEW);
//		intent.putExtra(ListBrowser.MGR, ListBrowser.MGR_CLASSFIED_LIST);
//		intent.putExtra(ClassifiedListManager.PARAM_URL_PATH_PREFIX, "?act=list");
//		
//		//intent.putExtra(ListBrowser.MGR, ListBrowser.MGR_SECTION_FOCUS);
//		startActivity(intent);
	}
	
	
	
	@Override
	protected Dialog onCreateDialog(int id) {
		String msg;
	    switch(id) {
	    case DIALOG_NETWORK_ERROR:
	    	msg = "Network error";
	        break;
	    default:
	        msg = "Message Not Defined";
	    }
	    AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(msg)
		       .setTitle("Error   ")
		       .setCancelable(false)
		       .setPositiveButton("Confirm", new DialogInterface.OnClickListener() {
		           public void onClick(DialogInterface dialog, int id) {
		                NewSMTHDroid.this.finish();
		           }
		       });
	    return builder.create();
	}
}
